# -*- coding;utf-8 -*-
"""
File name : ReadMarkdown2QuestionListMarked.py.PY
Program IDE : PyCharm
Create file time: 2024/8/11 10:49
File Create By Author : 朱清闯
"""
import os
import zipfile
from django.conf import settings
import datetime
import re
from PIL import Image
from utils.uploadfile import get_new_name

blank_char = re.compile('[\u3000\xa0]')
grade_rule = r'(高考|选考|高三|高二|高一|中考|九年级|八年级|七年级)'
question_choice_or_cloze_rule = r'^[一二三四]\s*、\s*(选择题|单项选择题|填空题|非选择题|多项选择题|判断题|是非选择题)\s*[\(（]'  # 匹配选择题或者填空题如一、选择题 二、填空题
question_type_rule = r"^[一二三四]\s*、\s*(选择题|单项选择题|填空题|非选择题|多项选择题|判断题|是非选择题|解答题)\s*[\(（:：]"  # 匹配题型，如一、选择题
question_number_rule = r"^(\.|．){0,3}(\d+)\s*(\.|．){1}\s*(.+)"  # 匹配小题号，如段首以1.开头, 并跳过开头加重点符号
answer_rule = r"^【答案】(.*)"  # 匹配答案，如【答案】xxx
explain_rule = r'^【解析】(.*)'  # 匹配解析，如【解析】xxx
difficulty_rule = r'^【难度】(\d)'
pattern_get_image_target = r"media/image\d{1,2}(.\w+)"
patten_image_name = r'media/(image\d{1,2}.\w+)'
pattern_del_tag = re.compile(r'<[^>]+>')  # 去掉标签<w:t>
pattern_get_text_between = r'>(.+)<'
pattern_get_imageId = r"(rId[\d+])"
pattern_date_rule = r'20(1|2)\d[-年]\d{1,2}[-月]\d{1,2}日*'
pattern_date_year_rule = r'(20\d{2})\s*(年|届|学年)'
pattern_date_month_rule = r'(\d{1,2})\s*月'
precondition_rule = r'阅读(下列|以下)材料[,，]\s*回答第\s*(\d{1,2})\s*[至-]\s*第{0,1}(\d{1,2})\s*小{0,1}题\s*'
pattern_answer_vocational_rule = re.compile(r'(试题答案)|(参考答案)')
image_dict = {}
type_dic = {'简答题': 0, '解答题': 0, '选择题': 1, '单项选择题': 1, '填空题': 2, '非选择题': 2, '多选题': 3, '多项选择题': 3,
            '判断题': 4, '是非选择题': 4}
grade_dic = {'选考': '4', '高考': '4', '高三': '3', '高二': '2', '高一': '1', '中考': '4', '九年级': '3', '八年级': '2',
             '七年级': '1'}
paper_dict = {'title': '', 'publish_time': '', 'grade': '4', 'open_level': 'public', 'is_joint': 'true'}
pattern_answer_detach = re.compile(r'(\d+)\s*[．\.]\s*答案\s*[：:](.*)')
pattern_answer_attach = re.compile(r'(\d+)\s*[．\.]\s*【答案】\s*(.*)')
pattern_explain_detach = re.compile(r'(\d+)\s*\.\s*解析\s*[：:](.*)')
pattern_answer_detach_no_number = re.compile(r'答案\s*[：:](.*)')
pattern_answer_attach_no_number = re.compile(r'【答案】\s*(.*)')
pattern_explain_detach_no_number = re.compile(r'解析\s*[：:](.*)')
pattern_explain_attach_no_number = re.compile(r'【解析】\s*(.*)')


def extract_image_marked(image_path):
    try:
        path_image = os.path.join(settings.BASE_DIR).replace('\\',
                                                             '/') + settings.IMAGE_TEMP_URL + 'images/' + image_path
        image = Image.open(path_image)
        MAX_PIXEL_WIDTH = 200
        MAX_PIXEL_HEIGHT = 200
        width = image.width
        height = image.height
        if width > MAX_PIXEL_WIDTH:
            height = int(height * MAX_PIXEL_WIDTH / width)
            width = MAX_PIXEL_WIDTH
        if height > MAX_PIXEL_HEIGHT:
            width = int(width * height / MAX_PIXEL_HEIGHT)
            height = MAX_PIXEL_HEIGHT
        img_url = settings.SERVER_IP + settings.IMAGE_TEMP_URL + 'images/' + image_path
        return f'<img src="{img_url}" width="{width}" height="{height}" alt="抱歉，服务器繁忙" >'
    except Exception as E:
        print('Exception:', E)
        return ''


def p_add_marked(text_str):
    return '<p>' + text_str + '</p>'


def search_order_index(question_list, order_search):
    index = -1
    for i in range(len(question_list) - 1, -1, -1):
        if question_list[i]['order'] == order_search:
            index = i
            break
    return index


def search_order_index_error(questions_list, order):
    write_index = -1
    if order == len(questions_list):
        write_index = len(questions_list) - 1
    # 题号超出试题列表，说明题目有漏题，或者题目不是从第1题开始的，查找当前order在question_list数组中的索引
    else:
        temp_index = search_order_index(questions_list, order)
        if temp_index > -1:
            write_index = temp_index
        else:
            print(f'第{order}题的答案未写入；<br>')
    return write_index


# 解压zip文件
def unzip_file(zip_path, extract_to):
    with zipfile.ZipFile(zip_path, 'r') as zip_ref:
        for file_info in zip_ref.infolist():
            # 解决中文文件名乱码问题
            file_info.filename = file_info.filename.encode('cp437').decode('gbk')
            zip_ref.extract(file_info, extract_to)


# 重命名文件夹下的所有文件名
def rename_images(folder_name):
    for root, _, files in os.walk(folder_name):
        for file in files:
            file_extension = os.path.splitext(file)[1]
            old_file_path = os.path.join(root, file)
            new_name = f"{get_new_name()}{file_extension}"
            new_file_path = os.path.join(root, new_name)
            os.rename(old_file_path, new_file_path)


# 遍历图片文件夹的内片文件名
def list_images_files(directory):
    for root, dirs, files in os.walk(directory):
        for file in files:
            print(os.path.join(root, file).replace('\\', '/'))


# 主函数
def main(zip_path):
    now = datetime.datetime.now()
    year_month = str(now.year) + str(now.month)
    # extract_to = settings.TEMP_ROOT + year_month
    extract_to = settings.TEMP_ROOT
    unzip_file(zip_path, extract_to)
    # images_folder = os.path.join(extract_to, 'images').replace('\\', '/')
    # if os.path.exists(images_folder):
    #     rename_images(images_folder)
    return extract_to


# 根据文件夹路径，读取该文件夹下面的mk文件
def get_mk_file_path(file_path):
    for root, dirs, files in os.walk(file_path):
        for file in files:
            if file.endswith('.md'):
                return os.path.join(root, file).replace('\\', '/')
    return None


# 读取md版本，且答案解析与试题分离
def read_markdown_file_detach(file_path):
    precondition_number_start = precondition_number_end = -1
    precondition_content = ""
    precondition_collect_over = True  # 收集前置情境是否结束，True表示结束
    is_answer_section = False
    current_type_cn = '选择题'
    questions_list = []  # 存放所有题目
    last_area = ''  # 记录上次填充的区域，共有answer、explain、content三种，用于判断空行文本时，应该填入哪个区域
    order = 0
    grade = 4
    write_index = 0
    partly_error = ''  # 记录部分答案错误的反馈信息
    result_flag = True  # 是否存在部分答案未录入，True代表全部正确，False代表部分答案未录入
    question_dict = {"content": "", "answer": "", "explain": "", "type": 1, "reference": "", "difficulty_level": 3,
                     "knowledgepoint": [], "knowledgepoint_cn": [], 'order': 1, 'bank_point': 1
                     }
    md_folder = main(file_path)
    md_file_path = get_mk_file_path(md_folder)
    with open(md_file_path, encoding='utf-8', errors='ignore') as file:
        paragraph_text = file.readline()
        # 包含没有标题，直接试题开始的特殊情况
        # 跳过开头几行的空行，来到有内容的第一行
        while paragraph_text.strip() == '':
            paragraph_text = file.readline()
        # 第一行试卷的标题填入“reference”字段，并填入paper的标题
        reference = paragraph_text.strip()
        question_dict["reference"] = reference
        paper_dict['title'] = reference
        # 第一行中提取年级，并存入"grade"字段
        if re.search(grade_rule, paragraph_text):
            grade = grade_dic[re.search(grade_rule, paragraph_text).group(1)]
            paper_dict["grade"] = str(grade)
            has_title = True
        # 第一行中提取试卷的时间，字典中填入“publish_time”字段
        publish_time = ''
        publish_year = ''
        if re.search(pattern_date_year_rule, paragraph_text):
            publish_year = re.search(pattern_date_year_rule, paragraph_text).group(1)
            publish_time += publish_year
        if re.search(pattern_date_month_rule, paragraph_text):
            publish_month = re.search(pattern_date_month_rule, paragraph_text).group(1)
            if publish_year != '':
                publish_time = publish_year + "-" + publish_month + "-" + "1"
                paper_dict["publish_time"] = publish_time
                question_dict['publish_time'] = publish_time
            has_title = True
        if has_title:
            paragraph_text = file.readline()
        while paragraph_text:
            if paragraph_text.strip() == '':
                paragraph_text = file.readline()
                continue
            p_text = blank_char.sub(' ', paragraph_text).replace("（", "(").replace('）', ')').replace('，', ',')
            # 匹配题型，如二、非选择题
            if re.match(question_type_rule, p_text) and not is_answer_section:
                current_type_cn = re.match(question_type_rule, p_text).group(1)
                precondition_collect_over = True
            # 匹配到题号，比如1.以下xxx, 先结算上一题的内容，添加到列表，再清空题目字典，最后把本行文本加入到新题目字典中，以及题号
            elif re.search(question_number_rule, p_text.strip(), re.M) and not is_answer_section:
                if len(question_dict["content"]) > 0:
                    questions_list.append(question_dict)
                    question_dict = {"content": "", "answer": "", "explain": "", "type_cn": current_type_cn,
                                     'type': type_dic[current_type_cn], "reference": reference,
                                     "difficulty_level": 3, "knowledgepoint": [], 'publish_time': publish_time,
                                     "knowledgepoint_cn": [], 'bank_point': 1
                                     }
                # order_last = int(order)
                content = re.search(question_number_rule, p_text, flags=re.M).group(4)
                order = re.search(question_number_rule, p_text, flags=re.M).group(2)
                order = int(order)
                question_dict['order'] = int(order)
                print('order:', order)
                last_area = 'content'
                # 在情境范围内，则情境问题放在最前面，并连接本次题号后的内容
                if precondition_number_start <= int(order) <= precondition_number_end:
                    question_dict['content'] = precondition_content + p_add_marked(content)
                # 情境超出题号范围，无须处理情境内容，只须把题号后的文本添加到新题的题干中
                else:
                    question_dict['content'] = p_add_marked(content)
                if int(order) == precondition_number_end:
                    precondition_content = ""
                # 停止收集情境文本, 用于遇到普通文本是，判断是否收集到情境中
                precondition_collect_over = True
            # 匹配到题号.答案：x或者【答案】x，比如1.答案：x或1.【答案】x。说明已经匹配到答案
            elif (pattern_answer_detach.search(p_text.strip()) or
                  pattern_answer_attach.search(p_text.strip())) and is_answer_section:
                match = pattern_answer_detach.search(p_text.strip())
                if not match:
                    match = pattern_answer_attach.search(p_text.strip())
                order = match.group(1)
                order = int(order)
                write_index = search_order_index_error(questions_list, order)
                if write_index > -1:
                    answer_content = match.group(2)
                    if len(answer_content) <= 4:
                        answer_content = answer_content.strip()
                    questions_list[write_index]['answer'] = p_add_marked(answer_content)
                    last_area = 'answer'
                    # print('答案部分的order:', order)
                else:
                    partly_error += f'第{order}题的答案未录入<br>'
                    result_flag = False
            # 匹配到答案：x，比如答案：x。说明已经匹配到答案，这是另一种格式
            elif (pattern_answer_detach_no_number.search(p_text.strip()) or
                  pattern_answer_attach_no_number.search(p_text.strip())) and is_answer_section:
                write_index = search_order_index_error(questions_list, order)
                if write_index > -1:
                    match = pattern_answer_detach_no_number.search(p_text.strip())
                    if not match:
                        match = pattern_answer_attach_no_number.search(p_text.strip())
                    answer_content = match.group(1)
                    if len(answer_content) <= 4:
                        answer_content = answer_content.strip()
                    questions_list[write_index]['answer'] = p_add_marked(answer_content)
                    last_area = 'answer'
                else:
                    partly_error += f'第{order}题的答案未录入<br>'
                    result_flag = False
            # 匹配到题号.解析：x，比如1.解析：x。说明已经匹配到解析
            elif pattern_explain_detach.search(p_text.strip()) and is_answer_section:
                match = pattern_explain_detach.search(p_text.strip())
                order = match.group(1)
                order = int(order)
                write_index = search_order_index_error(questions_list, order)
                if write_index > -1:
                    explain_content = match.group(2)
                    questions_list[write_index]['answer'] = p_add_marked(explain_content)
                    last_area = 'explain'
                    print('解析部分的order:', order)
                else:
                    partly_error += f'第{order}题的解析未录入<br>'
                    result_flag = False
            # 匹配到解析：或【解析】x，比如解析：x。说明已经匹配到解析，这是另一种格式
            elif (pattern_explain_detach_no_number.search(p_text.strip()) or
                  pattern_explain_attach_no_number.search(p_text.strip())) and is_answer_section:
                write_index = search_order_index_error(questions_list, order)
                if write_index > -1:
                    if pattern_explain_detach_no_number.search(p_text.strip()):
                        match = pattern_explain_detach_no_number.search(p_text.strip())
                    else:
                        match = pattern_explain_attach_no_number.search(p_text.strip())
                    explain_content = match.group(1)
                    questions_list[write_index]['explain'] = p_add_marked(explain_content)
                    last_area = 'explain'
                else:
                    partly_error += f'第{order}题的解析未录入<br>'
                    result_flag = False
            # 匹配到参考答案，结算最后一题题干
            elif pattern_answer_vocational_rule.search(p_text.strip()) and not is_answer_section:
                if question_dict['content'] != '':
                    questions_list.append(question_dict)
                is_answer_section = True
                precondition_collect_over = True
                print('匹配到参考答案')
            # 匹配到试题前置情境
            elif re.search(precondition_rule, p_text.strip(), re.M):
                precondition_number_start = int(re.search(precondition_rule, p_text).group(2))
                precondition_number_end = int(re.search(precondition_rule, p_text).group(3))
                precondition_content = p_add_marked(p_text)
                # 以下是初始化存储前置情境的变量，False表示已经情境范围未结束
                precondition_collect_over = False
            # 匹配到表格，并以<table>开头和</table>结束，不支持跨行
            elif p_text.strip()[:6] == '<table' and p_text.strip()[-8:] == '</table>':
                table_html = p_text
                # 处理表格内的图片, 插入服务器域名
                if '<img src="images/' in p_text.strip():
                    index = 0
                    s = p_text
                    server_ip = settings.SERVER_IP + '/static/temp/'
                    while index < len(s):
                        new_index = s.find("<img", index)
                        if new_index == -1:
                            break
                        # 插入服务器的域名
                        s = s[:new_index + len('<img src="')] + server_ip + s[new_index + len('<img src="'):]
                        index = new_index + len('<img src="') + len(server_ip)
                    table_html = s
                if not precondition_collect_over:
                    precondition_content += table_html
                else:
                    question_dict[last_area] += table_html
            # 匹配到表格（注意不支持跨行）
            elif p_text.strip()[0] == '|' and p_text.strip()[-1] == '|':
                table_html = '<table style="width: auto;" border="1"><tbody>'
                # 处理标题行
                table_html += '<tr>'
                p_text = p_text.strip()
                line = p_text.split('|')[1:-1]
                for cell in line:
                    table_html += '<th>{}</th>'.format(cell)
                table_html += '</tr>'
                p_text = file.readline()
                while p_text and p_text.strip() != '':
                    if p_text.strip()[0] == '|' and p_text.strip()[-1] == '|':
                        table_html += '<tr>'
                        p_text = p_text.strip()
                        line = p_text.split('|')[1:-1]
                        for cell in line:
                            table_html += '<td>{}</td>'.format(cell)
                        table_html += '</tr>'
                        paragraph_text = file.readline()
                        p_text = paragraph_text.strip()
                    else:
                        break
                table_html += '</tbody></table>'
                if not precondition_collect_over and not is_answer_section:
                    precondition_content += table_html
                elif not is_answer_section and len(question_dict['content']) > 0:
                    question_dict['content'] += table_html
                elif is_answer_section and len(questions_list[int(order) - 1][last_area]) > 0:
                    questions_list[write_index][last_area] += table_html
                # 因为本模块有p_text = file.readline()，因此需要跳过最后的p_text = file.readline()语句，避免重复
                continue
            # 以下处理图片部分
            elif p_text.strip()[:2] == '![':
                match = re.search(r'\(images/(.*?)\)', p_text)
                image_path = match.group(1)
                p_image_marked = extract_image_marked(image_path)
                if not precondition_collect_over and not is_answer_section:
                    precondition_content += p_add_marked(p_image_marked)
                elif not is_answer_section and len(question_dict['content']) > 0:
                    question_dict['content'] += p_add_marked(p_image_marked)
                elif is_answer_section and len(questions_list[write_index][last_area]) > 0:
                    questions_list[write_index][last_area] += p_image_marked
            # 非空行的文本内容，且未到参考答案部分，则添加到题干或情境中
            elif not is_answer_section:
                # 如果文本包含图片，且图片不是出现在开头
                has_image = False
                if '![' in p_text.strip():
                    match = re.search(r'\(images/(.*?)\)', p_text)
                    image_path = match.group(1)
                    p_image_marked = extract_image_marked(image_path)
                    content_before_image = p_text.split('![')[0]
                    has_image = True
                if not precondition_collect_over:
                    if has_image:
                        precondition_content += '<p>' + content_before_image + p_image_marked + '</p>'
                    else:
                        precondition_content += p_add_marked(p_text)
                elif len(question_dict['content']) > 0:
                    if has_image:
                        question_dict['content'] += '<p>' + content_before_image + p_image_marked + '</p>'
                    else:
                        question_dict['content'] += p_add_marked(p_text)
            # 非空行的文本内容，且到达参考答案部分，根据上次填充的内容，本地跟上次一样
            elif is_answer_section:
                # 如果文本包含图片，且图片不是出现在开头
                has_image = False
                if '![' in p_text.strip():
                    match = re.search(r'\(images/(.*?)\)', p_text)
                    image_path = match.group(1)
                    p_image_marked = extract_image_marked(image_path)
                    content_before_image = p_text.split('![')[0]
                    has_image = True
                if len(questions_list[write_index][last_area]) > 0:
                    if has_image:
                        questions_list[write_index][last_area] += '<p>' + content_before_image + p_image_marked + '</p>'
                    else:
                        questions_list[write_index][last_area] += p_add_marked(p_text)
            paragraph_text = file.readline()
    print('questions_list:', questions_list)
    return result_flag, partly_error, questions_list, paper_dict


# 读取md版本，且答案解析附在题后
def read_markdown_file_attach(file_path):
    precondition_number_start = precondition_number_end = -1
    precondition_content = ""
    precondition_collect_over = True  # 收集前置情境是否结束，True表示结束
    current_type_cn = '选择题'
    questions_list = []  # 存放所有题目
    last_area = ''  # 记录上次填充的区域，共有answer、explain、content三种，用于判断空行文本时，应该填入哪个区域
    order = 0
    write_index = 0
    partly_error = ''  # 记录部分答案错误的反馈信息
    result_flag = True  # 是否存在部分答案未录入，True代表全部正确，False代表部分答案未录入
    question_dict = {"content": "", "answer": "", "explain": "", "type": 1, "reference": "", "difficulty_level": 3,
                     "knowledgepoint": [], "knowledgepoint_cn": [], 'order': 1, 'bank_point': 1
                     }
    md_folder = main(file_path)
    # images_path = os.path.join(settings.TEMP_ROOT, 'images').replace('\\', '/')
    md_file_path = get_mk_file_path(md_folder)
    with open(md_file_path, encoding='utf-8', errors='ignore') as file:
        paragraph_text = file.readline()
        # 包含没有标题，直接试题开始的特殊情况
        # 跳过开头几行的空行，来到有内容的第一行
        while paragraph_text.strip() == '':
            paragraph_text = file.readline()
        # 第一行试卷的标题填入“reference”字段，并填入paper的标题
        reference = paragraph_text.strip()
        question_dict["reference"] = reference
        paper_dict['title'] = reference
        # 第一行中提取年级，并存入"grade"字段
        if re.search(grade_rule, paragraph_text):
            grade = grade_dic[re.search(grade_rule, paragraph_text).group(1)]
            paper_dict["grade"] = str(grade)
            has_title = True
        # 第一行中提取试卷的时间，字典中填入“publish_time”字段
        publish_time = ''
        publish_year = ''
        if re.search(pattern_date_year_rule, paragraph_text):
            publish_year = re.search(pattern_date_year_rule, paragraph_text).group(1)
            publish_time += publish_year
        if re.search(pattern_date_month_rule, paragraph_text):
            publish_month = re.search(pattern_date_month_rule, paragraph_text).group(1)
            if publish_year != '':
                publish_time = publish_year + "-" + publish_month + "-" + "1"
                paper_dict["publish_time"] = publish_time
                question_dict['publish_time'] = publish_time
            has_title = True
        if has_title:
            paragraph_text = file.readline()
        while paragraph_text:
            if paragraph_text.strip() == '':
                paragraph_text = file.readline()
                continue
            p_text = blank_char.sub(' ', paragraph_text).replace("（", "(").replace('）', ')').replace('，', ',')
            # 匹配题型，如二、非选择题
            if re.match(question_type_rule, p_text):
                current_type_cn = re.match(question_type_rule, p_text).group(1)
                precondition_collect_over = True
                # if len(questions_list) == 0:
                #     question_dict = {"content": "", "answer": "", "explain": "", "type_cn": current_type_cn,
                #                      'type': type_dic[current_type_cn], "reference": reference,
                #                      "difficulty_level": 3, "knowledgepoint": [], 'publish_time': publish_time,
                #                      "knowledgepoint_cn": [], 'bank_point': 1
                #                      }
                #     questions_list.append(question_dict)
            # 匹配到题号，比如1.以下xxx, 先结算上一题的内容，添加到列表，再清空题目字典，最后把本行文本加入到新题目字典中，以及题号
            elif re.search(question_number_rule, p_text.strip(), re.M):
                if len(question_dict["content"]) > 0:
                    questions_list.append(question_dict)
                    question_dict = {"content": "", "answer": "", "explain": "", "type_cn": current_type_cn,
                                     'type': type_dic[current_type_cn], "reference": reference,
                                     "difficulty_level": 3, "knowledgepoint": [], 'publish_time': publish_time,
                                     "knowledgepoint_cn": [], 'bank_point': 1
                                     }
                content = re.search(question_number_rule, p_text, flags=re.M).group(4)
                order = re.search(question_number_rule, p_text, flags=re.M).group(2)
                order = int(order)
                question_dict['order'] = int(order)
                print('order:', order)
                last_area = 'content'
                # 在情境范围内，则情境问题放在最前面，并连接本次题号后的内容
                if precondition_number_start <= int(order) <= precondition_number_end:
                    question_dict['content'] = precondition_content + p_add_marked(content)
                # 情境超出题号范围，无须处理情境内容，只须把题号后的文本添加到新题的题干中
                else:
                    question_dict['content'] = p_add_marked(content)
                if int(order) == precondition_number_end:
                    precondition_content = ""
                # 停止收集情境文本, 用于遇到普通文本是，判断是否收集到情境中
                precondition_collect_over = True
            # 匹配到题号.答案：x或者【答案】x，比如1.答案：x或1.【答案】x。说明已经匹配到答案
            elif pattern_answer_detach.search(p_text.strip()) or pattern_answer_attach.search(p_text.strip()):
                match = pattern_answer_attach.search(p_text.strip())
                if not match:
                    match = pattern_answer_detach.search(p_text.strip())
                order = match.group(1)
                order = int(order)
                answer_content = match.group(2)
                if len(answer_content) <= 4:
                    answer_content = answer_content.strip()
                question_dict['answer'] = p_add_marked(answer_content)
                last_area = 'answer'
                print('答案部分的order:', order)
            # 匹配到答案：x，比如答案：x。说明已经匹配到答案，这是另一种格式
            elif pattern_answer_attach_no_number.search(p_text.strip()) or \
                    pattern_answer_detach_no_number.search(p_text.strip()):
                match = pattern_answer_attach_no_number.search(p_text.strip())
                if not match:
                    match = pattern_answer_detach_no_number.search(p_text.strip())
                answer_content = match.group(1)
                if len(answer_content) <= 4:
                    answer_content = answer_content.strip()
                question_dict['answer'] = p_add_marked(answer_content)
                last_area = 'answer'
            # 匹配到解析：x或【解析】x，比如解析：x。说明已经匹配到解析，这是另一种格式
            elif pattern_explain_detach_no_number.search(p_text.strip()) or \
                    pattern_explain_attach_no_number.search(p_text.strip()):
                match = pattern_explain_attach_no_number.search(p_text.strip())
                if not match:
                    match = pattern_explain_detach_no_number.search(p_text.strip())
                explain_content = match.group(1)
                question_dict['explain'] = p_add_marked(explain_content)
                last_area = 'explain'
            # 匹配到试题前置情境
            elif re.search(precondition_rule, p_text.strip(), re.M):
                precondition_number_start = int(re.search(precondition_rule, p_text).group(2))
                precondition_number_end = int(re.search(precondition_rule, p_text).group(3))
                precondition_content = p_add_marked(p_text)
                # 以下是初始化存储前置情境的变量，False表示已经情境范围未结束
                precondition_collect_over = False
            # 匹配到表格（注意不支持跨行）
            elif p_text.strip()[0] == '|' and p_text.strip()[-1] == '|':
                table_html = '<table style="width: auto;" border="1"><tbody>'
                # 处理标题行
                table_html += '<tr>'
                p_text = p_text.strip()
                line = p_text.split('|')[1:-1]
                for cell in line:
                    table_html += '<th>{}</th>'.format(cell)
                table_html += '</tr>'
                p_text = file.readline()
                while p_text and p_text.strip() != '':
                    if p_text.strip()[0] == '|' and p_text.strip()[-1] == '|':
                        table_html += '<tr>'
                        p_text = p_text.strip()
                        line = p_text.split('|')[1:-1]
                        for cell in line:
                            table_html += '<td>{}</td>'.format(cell)
                        table_html += '</tr>'
                        paragraph_text = file.readline()
                        p_text = paragraph_text.strip()
                    else:
                        break
                table_html += '</tbody></table>'
                if not precondition_collect_over:
                    precondition_content += table_html
                else:
                    question_dict[last_area] += table_html
                # 因为本模块有p_text = file.readline()，因此需要跳过最后的p_text = file.readline()语句，避免重复
                continue
            # 匹配到表格，并以<table>开头和</table>结束，不支持跨行
            elif p_text.strip()[:7] == '<table>' and p_text.strip()[-8:] == '</table>':
                table_html = p_text
                # 处理表格内的图片, 插入服务器域名
                if '<img src="images/' in p_text.strip():
                    index = 0
                    s = p_text
                    server_ip = settings.SERVER_IP
                    while index < len(s):
                        new_index = s.find("<img", index)
                        if new_index == -1:
                            break
                        # 插入服务器的域名
                        s = s[:new_index + len('<img src="')] + server_ip + s[new_index + len('<img src="'):]
                        index = new_index + len('<img src="') + len(server_ip)
                    table_html = s
                if not precondition_collect_over:
                    precondition_content += table_html
                else:
                    question_dict[last_area] += table_html
            # 以下处理图片部分
            elif p_text.strip()[:2] == '![':
                match = re.search(r'\(images/(.*?)\)', p_text)
                image_path = match.group(1)
                p_image_marked = extract_image_marked(image_path)
                if not precondition_collect_over:
                    precondition_content += p_image_marked
                else:
                    question_dict[last_area] += p_image_marked
            # 非空行的文本内容，且未到参考答案部分，则添加到题干或情境中
            else:
                # 如果文本包含图片，且图片不是出现在开头
                has_image = False
                if '![' in p_text.strip():
                    match = re.search(r'\(images/(.*?)\)', p_text)
                    image_path = match.group(1)
                    p_image_marked = extract_image_marked(image_path)
                    content_before_image = p_text.split('![')[0]
                    has_image = True
                if not precondition_collect_over:
                    if has_image:
                        precondition_content += '<p>' + content_before_image + p_image_marked + '</p>'
                    else:
                        precondition_content += p_add_marked(p_text)
                else:
                    if has_image:
                        question_dict[last_area] += '<p>' + content_before_image + p_image_marked + '</p>'
                    else:
                        question_dict[last_area] += p_add_marked(p_text)
            paragraph_text = file.readline()
        questions_list.append(question_dict)
    print('questions_list:', questions_list)
    return result_flag, partly_error, questions_list, paper_dict
